### Elixir statements for the validations

from sqlalchemy_validations import *
from elixir.statements import Statement

class ValidationMixin(object):
    def is_valid(self):
        try:
            self.validate()
        except Invalid:
            return False
        
        return True
    
    def validate(self):
        for extension in entity._descriptor.mapper_options.get('extension', []):
            if isinstance(extension, Validator):
                extension.validate()
        
class ElixirStatement(object):
    def add_validation_to_entity(self, entity, validation):
        for extension in entity._descriptor.mapper_options.get('extension', []):
            if isinstance(extension, Validator):
                break
        else:
            extension = None
            
        if extension:
            extension.add_validation(validation)
        else:
            entity._descriptor.add_mapper_extension(Validator(validation))

class ElixirValidatesPresenceOf(ElixirStatement):
    def __init__(self, entity, *args, **kwargs):
        self.add_validation_to_entity(entity, presence_of(*args, **kwargs))

class ElixirValidatesRangeOf(ElixirStatement):
    def __init__(self, entity, fieldname, min, max, *args, **kwargs):
        self.add_validation_to_entity(entity, range_of(fieldname, min, max, *args, **kwargs))

class ElixirValidatesFormatOf(ElixirStatement):
    def __init__(self, entity, fieldname, *args, **kwargs):
        self.add_validation_to_entity(entity, format_of(fieldname, *args, **kwargs))

class ElixirValidatesFieldWithFormEncode(ElixirStatement):
    def __init__(self, entity, fieldname, fe_field_validator):
        self.add_validation_to_entity(entity, formencode_field_validator(fieldname, fe_field_validator))

class ElixirValidatesInstanceWithFormEncode(ElixirStatement):
    def __init__(self, entity, fe_instance_validator):
        self.add_validation_to_entity(entity, formencode_instance_validator(fe_instance_validator))



# Rails-like syntax for validators
validates_presence_of = Statement(ElixirValidatesPresenceOf)
validates_range_of    = Statement(ElixirValidatesRangeOf)
validates_format_of   = Statement(ElixirValidatesFormatOf)

# Generic formencode validators
validates_field_with_formencode = Statement(ElixirValidatesFieldWithFormEncode)
validates_with_formencode = Statement(ElixirValidatesInstanceWithFormEncode)

__all__ = ['Invalid'] + [name for name in globals().copy() if name.startswith('validates_')]